from plyny.plio.files import split, TemporaryFile, TemporaryDirectory, Path, FileWriter, mkdirs, listdir, list_by_ctime, File, Directory, open_path

import os
import datetime
import unittest

# XXX better handling/testing of symlinks

testfile = 'test/helloxxxxxx'

class TestCase(unittest.TestCase):
    def setUp(self):
        self.home = TemporaryDirectory()
#        self.assertFalse(os.path.exists(str(self.home.path().url())))

#    def test_directory_itr(self):
#        DirectoryIterator()

    def test_list_names(self):
        t = TemporaryDirectory()
        FileWriter(t / '.x').write('x')
        import time
        time.sleep(1)
        FileWriter(t / 'x').write('xxxx')
        time.sleep(1)
        FileWriter(t / 'y').write('xxxxxxxxxx')
        self.assertEquals(len(t.list_names()), 3)
        self.assertEquals(len(t.list_names().ignore_dot()), 2)

        l = t.list_names().by_date().paths()
        self.assertEquals(l[0].basename(), '.x')
        self.assertEquals(l[1].basename(), 'x')
        self.assertEquals(l[2].basename(), 'y')

        l = t.list_names().by_date().descending().paths()
        self.assertEquals(l[2].basename(), '.x')
        self.assertEquals(l[1].basename(), 'x')
        self.assertEquals(l[0].basename(), 'y')

        l = t.list_names().by_size().paths()
        self.assertEquals(l[0].basename(), '.x')
        self.assertEquals(l[1].basename(), 'x')
        self.assertEquals(l[2].basename(), 'y')

        l = t.list_names().by_name().paths()
        self.assertEquals(l[0].basename(), '.x')
        self.assertEquals(l[1].basename(), 'x')
        self.assertEquals(l[2].basename(), 'y')

        m = t.subdirectory('m').create()
        FileWriter(m / 'sup').write('ok')
        m2 = m.subdirectory('m2').create()
        l = list(t.list_names())
        self.assertEquals(len(l), 4)
        l = list(t.list_names().deep())
        self.assertEquals(len(l), 6)
        l = list(t.list_names().leaves())
        self.assertEquals(len(l), 4)
        l = list(t.list_names().leaves().files())
        self.assertEquals(len(l), 4)

        m3 = m2.subdirectory('m3').create()
        l = list(t.list_names().deep())
        self.assertEquals(len(l), 7)

#        for p in t.list_names().paths():
#            print p, type(p)

    def test_rename(self):
        t = TemporaryDirectory()
        x = TemporaryDirectory()
        y = x / 'hello.txt'
        y.write('sup')
        y = y.move(t)
        self.assertEquals(y.path().branch(), t.path())
        tl = list(t.list_names())
        tx = list(x.list_names())
        self.assertEquals(len(tl), 1)
        self.assertEquals(len(tx), 0)

        self.assertTrue(unicode(t.path()) in tl[0])
        x.move(t)
        tl = list(t.list_names())
        self.assertEquals(len(tl), 2)

    def test_split(self):
        t = self.home / 'test'
        t.write('1\n2\n3')
        split(open_path(str(t.path())), 3, str(self.home / 'test-'))

        l = list(self.home)
        self.assertEquals(len(l), 4)

        from string import ascii_letters

        for item in filter(lambda x: '-' in str(x), l):
            self.assertEquals(ascii_letters.index(str(item)[-1]),
                    int(list(item)[0].strip()) - 1)

    def test_subdirectory(self):
        t = TemporaryDirectory()
        t2 = t.subdirectory('xxxxx')
        t3 = t2.subdirectory('yyyyy')
        t2.create()
        t3.create()

        self.assertTrue(t2 in t)
#        raw_input()
        self.assertTrue(t3 in t)
        self.assertFalse(t in t2)
        self.assertFalse(t in t3)
        self.assertFalse(t2 in t3)
        self.assertTrue(t3 in t2)

    def test_temp(self):
        path = None
        t = TemporaryFile()
        size = 10
        lines = ['%d\n' % i for i in xrange(size)]
        writing = ''.join(lines)
        t.write(writing, overwrite=True)
        self.assertEquals(t.read(), writing)
        path = str(t.path())

        for i in xrange(size):
            for j in xrange(i + 1, size):
                self.assertEquals(list(t[i:]), lines[i:], i)
                self.assertEquals(list(t[:i]), lines[:i], i)
                self.assertEquals(list(t[i:j]), lines[i:j])
                self.assertEquals(t[i], lines[i], i)

                for by in xrange(1, 5):
                    self.assertEquals(map(int, t[i::by]), range(i, size, by))

        self.assertEquals(t.size(), 20)
        from util.stopwatch import Waiter, seconds_since

        self.assertTrue(seconds_since(t.atime()) < 2)
        self.assertTrue(seconds_since(t.mtime()) < 2)
        self.assertTrue(seconds_since(t.ctime()) < 2)

#        with Waiter(1):
#            pass
#        t.write('hi\n', True)

        # XXX need to do appending
#        print seconds_since(t.mtime())
#        print seconds_since(t.ctime())

        #self.assertEquals(list(t[0:-1]), list(t[0:None]))

        t = TemporaryFile()
        t.write('', True)
        self.assertRaises(IndexError, t.__getitem__, 2)

        del t

        self.assertFalse(os.path.exists(path))

        with TemporaryDirectory() as t:
            path = str(t.path())
            self.assertTrue(os.path.isdir(path))
        self.assertFalse(os.path.exists(path))
    
#    def test_url(self):
#        file_name = 'test.py'
#        a = File(file_name)
#        self.assertEquals(str(a.path().url()), 'file://' +
#                os.path.abspath(os.curdir) + '/' + file_name)
#
    def test_writer(self):
        global testfile
        fl = File(testfile)
        f = fl.writer(overwrite=True)
        self.assertFalse(os.path.exists(testfile))
        f.write('sup')

        did_once = False
        for line in open_path(testfile):
            did_once = True
            self.assertEquals(line, 'sup')
        self.assertTrue(did_once)

        self.assertTrue(os.path.exists(testfile))
        f.close()

        did_once = False
        for line in open_path(testfile):
            did_once = True
            self.assertEquals(line, 'sup')
        self.assertTrue(did_once)

        fl.remove()

        for suffix in ('gz', 'bz2'):
            tf = testfile + '.' + suffix
            fl = File(tf)
            f = fl.writer(overwrite=True)
            f.write('sup')
            f.close()

            for line in open_path(tf):
                self.assertEquals(line, 'sup')

            fl.remove()
    
    def test_lock(self):
        global testfile
        f = File(testfile)
        f.set_locked(True)
        self.assertRaises(IOError, f.write, ('sup'))

    def testStdio(self):
        f = open_path('-')
        #f.write('sup')
        #for item in f:
            #print f
    
    def testDiv(self):
        test_html = 'test_html'
        d = self.home / Directory(test_html)
        self.assertEquals(d.path(), self.home.path() + test_html)
        f = File('a.html')
        self.assertEquals(d / f, File('%s/%s/a.html' % (self.home.path()._url, test_html)))
        self.assertEquals(d / 'a', Directory('%s/%s/a' % (self.home.path()._url, test_html)))
    
    def test_path(self):
        p = Path('a/b/c/')
        self.assertEquals(p.basename(), 'c')
        self.assertEquals(p.branch(), 'a/b')
        for i, c in enumerate(p):
            if i == 0:
                self.assertEquals(c, 'a')
            elif i == 1:
                self.assertEquals(c, 'b')
            elif i == 2:
                self.assertEquals(c, 'c')

        p = Path('/a/b/c/')
        for i, c in enumerate(p):
            if i == 0:
                self.assertEquals(c, '/')
            elif i == 1:
                self.assertEquals(c, 'a')
            elif i == 2:
                self.assertEquals(c, 'b')
            elif i == 3:
                self.assertEquals(c, 'c')
    
        p = Path('///')
        self.assertEquals(p.basename(), '')
        self.assertEquals(p.branch(), '/')

        p = Path('ab.c.txt')
        self.assertEquals(p.extension(), 'txt')
        self.assertEquals(Path('a') + Path('b'), Path('a%sb' % os.path.sep))
        self.assertEquals(p.without_extention(), 'ab.c')

        p1 = Path('/path/to/whatever')
        p2 = Path('/path/to/nothing')

        self.assertEquals(p1 % p2, Path('whatever'))

        p1 = Path('path/to/whatever')
        p2 = Path('path/to/nothing')
        self.assertEquals(p1 % p2, Path('whatever'))

        p1 = Path('Data/www/ajax.googleapis.com/ajax/services/search/web?q=Alpacas&start=4&v=1.0')
        p2 = Path('Data/www/ajax.googleapis.com')
        self.assertEquals(p1 % p2, Path('ajax/services/search/web?q=Alpacas&start=4&v=1.0'))

    def test_expansion(self):
        f = open_path('~/test/hello')
        s = str(f.path())
        self.assertTrue(s.startswith('/'))  # proof that was made absolute
        self.assertFalse('~' in s)
    
    def testExists(self):
        f = File.from_dir(self.home, 'test')
        self.assertFalse(f.exists())
        f2 = self.home.open_within('test')
        self.assertEquals(f, f2)
        f.write('hello')
        self.assertTrue(f.exists())
        f.remove()
        self.assertFalse(f.exists())
    
    def testDir(self):
        d = Directory.from_dir(self.home, 'tessst' + os.path.sep + 'aaaa')
        self.assertFalse(d.exists())
        d.create_unless_exists()
        self.assertTrue(d.exists())
        d.create_unless_exists()
        d.remove(True)
        self.assertFalse(d.exists())
        dir = d.path() / Path('a/b/c/')
        mkdirs(dir)
        self.assertTrue(open_path(dir).exists())
        dir = str(d.path() / Path('b/c/a'))
        self.assertTrue(isinstance(dir, basestring))
        mkdirs(dir)
        self.assertTrue(open_path(dir).exists())

    def test_append(self):
        t = TemporaryDirectory()
        f = (t / 'a').writer()
        f.write('1')
        f.write('2')
        f.close()

        f = (t / 'a')
        x = f.writer(append=True)
        x.write('3')
        self.assertEquals(f.read(), '123')

    def test_read(self):
        f = TemporaryFile()
        f.write('0\n1\n2\n3\n4\n5\n', True)
        self.assertEquals(list(f.stripped()), [str(x) for x in xrange(6)])
        self.assertEquals(list(f.stripped()[1:6]), [str(x) for x in xrange(1, 6)])
        self.assertEquals(list(map(int, f)), [x for x in xrange(6)])

    def tearDown(self):
        if os.path.exists(testfile):
            os.remove(testfile)
        self.home.remove(True)

if __name__ == '__main__':
    unittest.main()
